Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
13.04% |
3 / 23 |
CRAP | |
63.08% |
41 / 65 |
| PitchClassSet | |
0.00% |
0 / 1 |
|
13.04% |
3 / 23 |
101.24 | |
63.08% |
41 / 65 |
| __construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
| constructFromTones | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| forteNumber | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| carterNumber | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getInteriorIntervals | |
0.00% |
0 / 1 |
3.01 | |
91.67% |
11 / 12 |
|||
| anonymous function | |
100.00% |
1 / 1 |
4 | |
100.00% |
7 / 7 |
|||
| primeFormForte | |
100.00% |
1 / 1 |
8 | |
100.00% |
14 / 14 |
|||
| primeFormRahn | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| primeFormRing | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| intervalVector | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| normalMatrix | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| cardinality | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| cardinalityTerm | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 4 |
|||
| zRelations | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| tnInvariance | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| tniInvariance | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| applyTransformation | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| getTransformation | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| invert | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| complement | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| isDeepScale | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| voiceLeadingTransform | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| combinatoriality | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 1 |
|||
| <?php | |
| /** | |
| * PitchClassSet Class | |
| * | |
| * PitchClassSet internally represents a PCS the same way that Scale represents a scale; as a bitmask word of 12 bits. | |
| * Set theory typically calls the first position "0", but in bits that first spot is equal to 1. So we need to be | |
| * cognizant of that in our maths. | |
| * | |
| * @package PHPMusicTools | |
| * @author Ian Ring <httpwebwitch@email.com> | |
| */ | |
| namespace ianring; | |
| require_once 'PMTObject.php'; | |
| require_once 'Utils/BitmaskUtils.php'; | |
| /** | |
| * Accidental Class | |
| */ | |
| class PitchClassSet extends PMTObject { | |
| /** | |
| * Constructor. | |
| * | |
| */ | |
| public function __construct($bits) { | |
| $this->bits = $bits; | |
| } | |
| /** | |
| * constructs the object from an array serialization | |
| * | |
| * @param array $props the array of properties | |
| * @return Accidental the Accidental object. | |
| */ | |
| public static function constructFromTones($tones) { | |
| $bits = BitmaskUtils::tones2Bits($tones); | |
| return new PitchClassSet($bits); | |
| } | |
| public function forteNumber() { | |
| } | |
| public function carterNumber() { | |
| } | |
| private function getInteriorIntervals($bits) { | |
| $tones = BitmaskUtils::bits2Tones($bits); | |
| if (count($tones) == 0) { | |
| return 0; | |
| } | |
| sort($tones); | |
| $lowestTone = $tones[0]; | |
| array_walk($tones, function(&$item, $key, $lowestTone) { | |
| $item = $item - $lowestTone; | |
| }, $lowestTone); | |
| // express it as intervals; add a final interval so it reaches an octave | |
| $intervals = array(); | |
| for ($i=0; $i<count($tones)-1; $i++) { | |
| $intervals[] = $tones[$i+1] - $tones[$i]; | |
| } | |
| $intervals[] = 12 - $tones[count($tones)-1]; | |
| return $intervals; | |
| } | |
| /** | |
| * returns the prime form of this PCS according to Forte's algorithm. Inversions are excluded as duplicates! | |
| */ | |
| public function primeFormForte() { | |
| // shortcut | |
| if ($this->bits == 0) { | |
| return 0; | |
| } | |
| $rotations = array(); | |
| $intervals = $this->getInteriorIntervals($this->bits); | |
| // create rotations of this set of intervals | |
| $count = count($intervals); | |
| for($i=0; $i<$count; $i++) { | |
| $rotations[] = $intervals; | |
| array_push($intervals, array_shift($intervals)); | |
| } | |
| // invert, and get those ones too | |
| $inversion = \ianring\BitmaskUtils::reflectBitmask($this->bits); | |
| $iIntervals = $this->getInteriorIntervals($inversion); | |
| $count = count($iIntervals); | |
| for($i=0; $i<$count; $i++) { | |
| $rotations[] = $iIntervals; | |
| array_push($iIntervals, array_shift($iIntervals)); | |
| } | |
| // now sort all the PCSs for leftmost density | |
| usort($rotations, function($a, $b){ | |
| // biggest interval at the end, | |
| if ($a[count($a)-1] !== $b[count($b)-1]) { | |
| return $a[count($a)-1] < $b[count($b)-1]; | |
| } | |
| // smaller interval at the beginning | |
| for ($i=0; $i<count($a); $i++) { | |
| if ($a[$i] !== $b[$i]) { | |
| return $a[$i] > $b[$i]; | |
| } | |
| } | |
| return 0; | |
| }); | |
| $primeRotation = $rotations[0]; | |
| // turn the intervals back into tones | |
| $p = 0; | |
| $tones = array(0); | |
| for ($i=0; $i<count($primeRotation)-1; $i++) { | |
| $p += $primeRotation[$i]; // add the interval... | |
| $tones[] = $p; | |
| } | |
| return \ianring\BitmaskUtils::tones2Bits($tones); | |
| } | |
| /** | |
| * returns the prime form of this PCS according to Rahn's algorithm | |
| */ | |
| private function primeFormRahn() { | |
| } | |
| /** | |
| * returns the prime form of this PCS according to Ring's criteria (bitmask with the lowest value) | |
| */ | |
| private function primeFormRing() { | |
| } | |
| /** | |
| * returns the interval vector as an array of integers | |
| * @return array | |
| */ | |
| public function intervalVector() { | |
| return \ianring\BitmaskUtils::spectrum($this->bits); | |
| } | |
| public function normalMatrix() { | |
| } | |
| /** | |
| * returns the cardinality of the pitch class set, aka the number of tones in it | |
| * | |
| * @return int | |
| */ | |
| public function cardinality() { | |
| return count(\ianring\BitmaskUtils::countOnBits($this->bits)); | |
| } | |
| /** | |
| * @return string | |
| */ | |
| public static function cardinalityTerm($card) { | |
| $terms = array( | |
| 2 => 'dyad', | |
| 3 => 'trichord', | |
| 4 => 'tetrachord', | |
| 5 => 'pentachord', | |
| 6 => 'hexachord' | |
| ); | |
| if (in_array($card, $terms)) { | |
| return $terms[$card]; | |
| } | |
| return null; | |
| } | |
| /** | |
| * When two prime forms have the same internal vector, and when one can not be reduced to the other | |
| * (by inversion or transposition), they are said to be "Z-Related". | |
| */ | |
| public function zRelations() { | |
| } | |
| public function tnInvariance() { | |
| } | |
| public function tniInvariance() { | |
| } | |
| public function applyTransformation($t) { | |
| } | |
| /** | |
| * Returns the PitchClassSetTransformation for what it would take to transform $set1 into $set2. | |
| * For example, a rotation of one semitone is "T1". An inversion and rotation of five semitones is "T5I". | |
| * | |
| * @return PitchClassSetTransformation | |
| */ | |
| public static function getTransformation($set1, $set2) { | |
| } | |
| /** | |
| * returns the PCS that is the inverse of this one | |
| * | |
| * @return PitchClassSet | |
| */ | |
| public function invert() { | |
| } | |
| /** | |
| * The complement of a PCS is one where all the off bits are on, and the on bits are off. | |
| * | |
| * @return PitchClassSet | |
| */ | |
| public function complement() { | |
| } | |
| /** | |
| * A scale whose interval vector has six unique digits is said to have the "deep scale" property. | |
| * @return bool | |
| */ | |
| public function isDeepScale() { | |
| } | |
| /** | |
| * A voice leading transform is one where an integer transposition is applied to each member of the PCS. | |
| * For example, consider the PCS of a major triad, [0,4,7]. We can transform that into a minor triad by | |
| * transposing the second tone down a semitone, so the 4 becomes a 3, and the result is [0,3,7]. | |
| * The "voice leading transformation" in this case is [0,-1,0]. | |
| * | |
| * @see http://dmitri.mycpanel.princeton.edu/files/publications/fourier.pdf | |
| * | |
| */ | |
| public function voiceLeadingTransform($transformation) { | |
| } | |
| /** | |
| * returns boolean, indicating whether a number appears x times in a set's matrix, where x is the length of the set | |
| * @see http://www.jaytomlin.com/music/settheory/help.html#forte | |
| */ | |
| public function combinatoriality() { | |
| } | |
| } |